home *** CD-ROM | disk | FTP | other *** search
/ CD Actual 1 / PC Actual CD 01.iso / f1 / mdisk25.arj / MHELP.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1994-08-31  |  19.3 KB  |  850 lines

  1. {************************************************}
  2. {                                                }
  3. {   Turbo Pascal 6.0                             }
  4. {   Turbo Vision Demo                            }
  5. {   Copyright (c) 1990 by Borland International  }
  6. {                                                }
  7. {************************************************}
  8.  
  9. { Modificaciones del módulo HElp para su uso con MDiskpro }
  10. { modificaciones (c) Emilio David Diaus López 1994        }
  11.  
  12. Unit Mhelp;
  13.  
  14. {$F+,O+,X+,S-,D-,L-}
  15.  
  16. Interface
  17.  
  18. Uses Objects, Drivers, Views;
  19.  
  20. Const
  21.   Chelpcolor      = #$17#$1F#$1E#$1B#$1B#$1E#$70#$7B;
  22.   Chelpblackwhite = #$07#$0F#$07#$70#$70#$07#$0F#$70;
  23.   Chelpmonochrome = #$07#$0F#$07#$70#$70#$07#$0F#$70;
  24.   Chelpviewer     = #6#7#8;
  25.   Chelpwindow     = #64#65#66#67#68#69#70#71;
  26.  
  27. Type
  28.  
  29. { TParagraph }
  30.  
  31.   Pparagraph = ^Tparagraph;
  32.   Tparagraph = Record
  33.     Next: Pparagraph;
  34.     Wrap: Boolean;
  35.     Size: Word;
  36.     Text: Record End;
  37.   End;
  38.  
  39. { THelpTopic }
  40.  
  41.   Tcrossref = Record
  42.     Ref: Integer;
  43.     Offset: Integer;
  44.     Length: Byte;
  45.   End;
  46.  
  47.   Pcrossrefs = ^Tcrossrefs;
  48.   Tcrossrefs = Array[1..10000] Of Tcrossref;
  49.   Tcrossrefhandler = Procedure (Var S: Tstream; Xrefvalue: Integer);
  50.  
  51.   Phelptopic = ^Thelptopic;
  52.   Thelptopic = Object(Tobject)
  53.     Constructor Init;
  54.     Constructor Load(Var S: Tstream);
  55.     Destructor Done; Virtual;
  56.     Procedure Addcrossref(Ref: Tcrossref);
  57.     Procedure Addparagraph(P: Pparagraph);
  58.     Procedure Getcrossref(I: Integer; Var Loc: Tpoint; Var Length: Byte;
  59.       Var Ref: Integer);
  60.     Function Getline(Line: Integer): String;
  61.     Function Getnumcrossrefs: Integer;
  62.     Function Numlines: Integer;
  63.     Procedure Setcrossref(I: Integer; Var Ref: Tcrossref);
  64.     Procedure Setnumcrossrefs(I: Integer);
  65.     Procedure Setwidth(Awidth: Integer);
  66.     Procedure Store(Var S: Tstream);
  67.   Private
  68.     Paragraphs: Pparagraph;
  69.     Numrefs: Integer;
  70.     Crossrefs: Pcrossrefs;
  71.     Width: Integer;
  72.     Lastoffset: Integer;
  73.     Lastline: Integer;
  74.     Lastparagraph: Pparagraph;
  75.     Function Wraptext(Var Text; Size: Integer; Var Offset: Integer;
  76.       Wrap: Boolean): String;
  77.   End;
  78.  
  79. { THelpIndex }
  80.  
  81.   Pindexarray = ^Tindexarray;
  82.   Tindexarray = Array[0..16380] Of Longint;
  83.  
  84.   Phelpindex = ^Thelpindex;
  85.   Thelpindex = Object(Tobject)
  86.     Size: Word;
  87.     Index: Pindexarray;
  88.     Constructor Init;
  89.     Constructor Load(Var S: Tstream);
  90.     Destructor Done; Virtual;
  91.     Function Position(I: Integer): Longint;
  92.     Procedure Add(I: Integer; Val: Longint);
  93.     Procedure Store(Var S: Tstream);
  94.   End;
  95.  
  96. { THelpFile }
  97.  
  98.   Phelpfile = ^Thelpfile;
  99.   Thelpfile = Object(Tobject)
  100.     Stream: Pstream;
  101.     Modified: Boolean;
  102.     Constructor Init(S: Pstream);
  103.     Destructor Done; Virtual;
  104.     Function Gettopic(I: Integer): Phelptopic;
  105.     Function Invalidtopic: Phelptopic;
  106.     Procedure Recordpositioninindex(I: Integer);
  107.     Procedure Puttopic(Topic: Phelptopic);
  108.   Private
  109.     Index: Phelpindex;
  110.     Indexpos: Longint;
  111.   End;
  112.  
  113. { THelpViewer }
  114.  
  115.   Phelpviewer = ^Thelpviewer;
  116.   Thelpviewer = Object(Tscroller)
  117.     Hfile: Phelpfile;
  118.     Topic: Phelptopic;
  119.     Selected: Integer;
  120.     Constructor Init(Var Bounds: Trect; Ahscrollbar,
  121.       Avscrollbar: Pscrollbar; Ahelpfile: Phelpfile; Context: Word);
  122.     Destructor Done; Virtual;
  123.     Procedure Changebounds(Var Bounds: Trect); Virtual;
  124.     Procedure Draw; Virtual;
  125.     Function Getpalette: Ppalette; Virtual;
  126.     Procedure Handleevent(Var Event: Tevent); Virtual;
  127.   End;
  128.  
  129. { THelpWindow }
  130.  
  131.   Phelpwindow = ^Thelpwindow;
  132.   Thelpwindow = Object(Twindow)
  133.     Constructor Init(Hfile: Phelpfile; Context: Word);
  134.     Function Getpalette: Ppalette; Virtual;
  135.   End;
  136.  
  137. Const
  138.  
  139.   Rhelptopic: Tstreamrec = (
  140.      Objtype: 10000;
  141.      Vmtlink: Ofs(Typeof(Thelptopic)^);
  142.      Load:    @Thelptopic.Load;
  143.      Store:   @Thelptopic.Store
  144.   );
  145.   Rhelpindex: Tstreamrec = (
  146.      Objtype: 10001;
  147.      Vmtlink: Ofs(Typeof(Thelpindex)^);
  148.      Load:    @Thelpindex.Load;
  149.      Store:   @Thelpindex.Store
  150.   );
  151.  
  152. Procedure Registerhelpfile;
  153.  
  154. Procedure Notassigned(Var S: Tstream; Value: Integer);
  155.  
  156. Const
  157.   Crossrefhandler: Tcrossrefhandler = Notassigned;
  158.  
  159. Implementation
  160.  
  161. { THelpTopic }
  162.  
  163. Constructor Thelptopic.Init;
  164. Begin
  165.   Tobject.Init;
  166.   Lastline := Maxint;
  167. End;
  168.  
  169. Constructor Thelptopic.Load(Var S: Tstream);
  170.  
  171. Procedure Readparagraphs;
  172. Var
  173.   I, Size: Integer;
  174.   Pp: ^Pparagraph;
  175. Begin
  176.   S.Read(I, Sizeof(I));
  177.   Pp := @Paragraphs;
  178.   While I > 0 Do
  179.   Begin
  180.     S.Read(Size, Sizeof(Size));
  181.     Getmem(Pp^, Sizeof(Pp^^) + Size);
  182.     Pp^^.Size := Size;
  183.     S.Read(Pp^^.Wrap, Sizeof(Boolean));
  184.     S.Read(Pp^^.Text, Size);
  185.     Pp := @Pp^^.Next;
  186.     Dec(I);
  187.   End;
  188.   Pp^ := Nil;
  189. End;
  190.  
  191. Procedure Readcrossrefs;
  192. Begin
  193.   S.Read(Numrefs, Sizeof(Integer));
  194.   Getmem(Crossrefs, Sizeof(Tcrossref) * Numrefs);
  195.   S.Read(Crossrefs^, Sizeof(Tcrossref) * Numrefs);
  196. End;
  197.  
  198. Begin
  199.   Readparagraphs;
  200.   Readcrossrefs;
  201.   Width := 0;
  202.   Lastline := Maxint;
  203. End;
  204.  
  205. Destructor Thelptopic.Done;
  206.  
  207. Procedure Disposeparagraphs;
  208. Var
  209.   P, T: Pparagraph;
  210. Begin
  211.   P := Paragraphs;
  212.   While P <> Nil Do
  213.   Begin
  214.     T := P;
  215.     P := P^.Next;
  216.     Freemem(T, Sizeof(T^) + T^.Size);
  217.   End;
  218. End;
  219.  
  220. Begin
  221.   Disposeparagraphs;
  222.   Freemem(Crossrefs, Sizeof(Tcrossref) * Numrefs);
  223.   Tobject.Done
  224. End;
  225.  
  226. Procedure Thelptopic.Addcrossref(Ref: Tcrossref);
  227. Var
  228.   P: Pcrossrefs;
  229. Begin
  230.   Getmem(P, (Numrefs+1) * Sizeof(Tcrossref));
  231.   If Numrefs > 0 Then
  232.   Begin
  233.     Move(Crossrefs^, P^, Numrefs * Sizeof(Tcrossref));
  234.     Freemem(Crossrefs, Numrefs * Sizeof(Tcrossref));
  235.   End;
  236.   Crossrefs^[Numrefs] := Ref;
  237.   Inc(Numrefs);
  238. End;
  239.  
  240. Procedure Thelptopic.Addparagraph(P: Pparagraph);
  241. Var
  242.   Pp: ^Pparagraph;
  243. Begin
  244.   Pp := @Paragraphs;
  245.   While Pp^ <> Nil Do
  246.     Pp := @Pp^^.Next;
  247.   Pp^ := P;
  248.   P^.Next := Nil;
  249. End;
  250.  
  251. Procedure Thelptopic.Getcrossref(I: Integer; Var Loc: Tpoint;
  252.   Var Length: Byte; Var Ref: Integer);
  253. Var
  254.   Oldoffset, Curoffset, Offset, Paraoffset: Integer;
  255.   P: Pparagraph;
  256.   Line: Integer;
  257. Begin
  258.   Paraoffset := 0;
  259.   Curoffset := 0;
  260.   Oldoffset := 0;
  261.   Line := 0;
  262.   Offset := Crossrefs^[I].Offset;
  263.   P := Paragraphs;
  264.   While Paraoffset+Curoffset < Offset Do
  265.   Begin
  266.     Oldoffset := Paraoffset + Curoffset;
  267.     Wraptext(P^.Text, P^.Size, Curoffset, P^.Wrap);
  268.     Inc(Line);
  269.     If Curoffset >= P^.Size Then
  270.     Begin
  271.       Inc(Paraoffset, P^.Size);
  272.       P := P^.Next;
  273.       Curoffset := 0;
  274.     End;
  275.   End;
  276.   Loc.X := Offset - Oldoffset - 1;
  277.   Loc.Y := Line;
  278.   Length := Crossrefs^[I].Length;
  279.   Ref := Crossrefs^[I].Ref;
  280. End;
  281.  
  282. Function Thelptopic.Getline(Line: Integer): String;
  283. Var
  284.   Offset, I: Integer;
  285.   P: Pparagraph;
  286. Begin
  287.   If Lastline < Line Then
  288.   Begin
  289.     I := Line;
  290.     Dec(Line, Lastline);
  291.     Lastline := I;
  292.     Offset := Lastoffset;
  293.     P := Lastparagraph;
  294.   End
  295.   Else
  296.   Begin
  297.     P := Paragraphs;
  298.     Offset := 0;
  299.     Lastline := Line;
  300.   End;
  301.   Getline := '';
  302.   While (P <> Nil) Do
  303.   Begin
  304.     While Offset < P^.Size Do
  305.     Begin
  306.       Dec(Line);
  307.       Getline := Wraptext(P^.Text, P^.Size, Offset, P^.Wrap);
  308.       If Line = 0 Then
  309.       Begin
  310.         Lastoffset := Offset;
  311.         Lastparagraph := P;
  312.         Exit;
  313.       End;
  314.     End;
  315.     P := P^.Next;
  316.     Offset := 0;
  317.   End;
  318.   Getline := '';
  319. End;
  320.  
  321. Function Thelptopic.Getnumcrossrefs: Integer;
  322. Begin
  323.   Getnumcrossrefs := Numrefs;
  324. End;
  325.  
  326. Function Thelptopic.Numlines: Integer;
  327. Var
  328.   Offset, Lines: Integer;
  329.   P: Pparagraph;
  330. Begin
  331.   Offset := 0;
  332.   Lines := 0;
  333.   P := Paragraphs;
  334.   While P <> Nil Do
  335.   Begin
  336.     Offset := 0;
  337.     While Offset < P^.Size Do
  338.     Begin
  339.       Inc(Lines);
  340.       Wraptext(P^.Text, P^.Size, Offset, P^.Wrap);
  341.     End;
  342.     P := P^.Next;
  343.   End;
  344.   Numlines := Lines;
  345. End;
  346.  
  347. Procedure Thelptopic.Setcrossref(I: Integer; Var Ref: Tcrossref);
  348. Begin
  349.   If I <= Numrefs Then Crossrefs^[I] := Ref;
  350. End;
  351.  
  352. Procedure Thelptopic.Setnumcrossrefs(I: Integer);
  353. Var
  354.   P: Pcrossrefs;
  355. Begin
  356.   If Numrefs = I Then Exit;
  357.   Getmem(P, I * Sizeof(Tcrossref));
  358.   If Numrefs > 0 Then
  359.   Begin
  360.     If I > Numrefs Then Move(Crossrefs^, P^, Numrefs * Sizeof(Tcrossref))
  361.     Else Move(Crossrefs^, P^, I * Sizeof(Tcrossref));
  362.     Freemem(Crossrefs, Numrefs * Sizeof(Tcrossref));
  363.   End;
  364.   Crossrefs := P;
  365.   Numrefs := I;
  366. End;
  367.  
  368. Procedure Thelptopic.Setwidth(Awidth: Integer);
  369. Begin
  370.   Width := Awidth;
  371. End;
  372.  
  373. Procedure Thelptopic.Store(Var S: Tstream);
  374.  
  375. Procedure Writeparagraphs;
  376. Var
  377.   I: Integer;
  378.   P: Pparagraph;
  379. Begin
  380.   P := Paragraphs;
  381.   I := 0;
  382.   While P <> Nil Do
  383.   Begin
  384.     Inc(I);
  385.     P := P^.Next;
  386.   End;
  387.   S.Write(I, Sizeof(I));
  388.   P := Paragraphs;
  389.   While P <> Nil Do
  390.   Begin
  391.     S.Write(P^.Size, Sizeof(Integer));
  392.     S.Write(P^.Wrap, Sizeof(Boolean));
  393.     S.Write(P^.Text, P^.Size);
  394.     P := P^.Next;
  395.   End;
  396. End;
  397.  
  398. Procedure Writecrossrefs;
  399. Var
  400.   I: Integer;
  401. Begin
  402.   S.Write(Numrefs, Sizeof(Integer));
  403.   If @Crossrefhandler = @Notassigned Then
  404.     S.Write(Crossrefs^, Sizeof(Tcrossref) * Numrefs)
  405.   Else
  406.     For I := 1 To Numrefs Do
  407.     Begin
  408.       Crossrefhandler(S, Crossrefs^[I].Ref);
  409.       S.Write(Crossrefs^[I].Offset, Sizeof(Integer) + Sizeof(Byte));
  410.     End;
  411. End;
  412.  
  413. Begin
  414.   Writeparagraphs;
  415.   Writecrossrefs;
  416. End;
  417.  
  418. Function Thelptopic.Wraptext(Var Text; Size: Integer;
  419.   Var Offset: Integer; Wrap: Boolean): String;
  420. Type
  421.   Pcarray = ^Carray;
  422.   Carray = Array[0..32767] Of Char;
  423. Var
  424.   Line: String;
  425.   I, P: Integer;
  426.  
  427. Function Isblank(Ch: Char): Boolean;
  428. Begin
  429.   Isblank := (Ch = ' ') Or (Ch = #13) Or (Ch = #10);
  430. End;
  431.  
  432. Function Scan(Var P; Offset: Integer; C: Char): Integer; Assembler;
  433. Asm
  434.     Cld
  435.     Les    Di,p
  436.         Add    Di,&Offset
  437.     Mov    Cx,256
  438.     Mov    Al, c
  439.         Repne    Scasb
  440.     Sub    Cx,256
  441.         Neg    Cx
  442.         Xchg    Ax,Cx
  443. End;
  444.  
  445. Procedure Texttoline(Var Text; Offset, Length: Integer; Var Line: String);
  446.   Assembler;
  447. Asm
  448.     Cld
  449.     Push    Ds
  450.     Lds    Si,Text
  451.         Add    Si,&Offset
  452.         Les     Di,Line
  453.         Mov    Ax,Length
  454.         Stosb
  455.         Xchg    Ax,Cx
  456.         Rep    Movsb
  457.         Pop    Ds
  458. End;
  459.  
  460. Begin
  461.   I := Scan(Text, Offset, #13);
  462.   If I + Offset > Size Then I := Size - Offset;
  463.   If (I >= Width) And Wrap Then
  464.   Begin
  465.     I := Offset + Width;
  466.     If I > Size Then I := Size
  467.     Else
  468.     Begin
  469.       While (I > Offset) And Not Isblank(Pcarray(@Text)^[I]) Do Dec(I);
  470.       If I = Offset Then I := Offset + Width
  471.       Else Inc(I);
  472.     End;
  473.     If I = Offset Then I := Offset + Width;
  474.     Dec(I, Offset);
  475.   End;
  476.   Texttoline(Text, Offset, I, Line);
  477.   If Line[Length(Line)] = #13 Then Dec(Line[0]);
  478.   Inc(Offset, I);
  479.   Wraptext := Line;
  480. End;
  481.  
  482. { THelpIndex }
  483.  
  484. Constructor Thelpindex.Init;
  485. Begin
  486.   Tobject.Init;
  487.   Size := 0;
  488.   Index := Nil;
  489. End;
  490.  
  491. Constructor Thelpindex.Load(Var S: Tstream);
  492. Begin
  493.   S.Read(Size, Sizeof(Size));
  494.   If Size = 0 Then Index := Nil
  495.   Else
  496.   Begin
  497.     Getmem(Index, Sizeof(Longint) * Size);
  498.     S.Read(Index^, Sizeof(Longint) * Size);
  499.   End;
  500. End;
  501.  
  502. Destructor Thelpindex.Done;
  503. Begin
  504.   Freemem(Index, Sizeof(Longint) * Size);
  505.   Tobject.Done;
  506. End;
  507.  
  508. Function Thelpindex.Position(I: Integer): Longint;
  509. Begin
  510.   If I < Size Then Position := Index^[I]
  511.   Else Position := -1;
  512. End;
  513.  
  514. Procedure Thelpindex.Add(I: Integer; Val: Longint);
  515. Const
  516.   Delta = 10;
  517. Var
  518.   P: Pindexarray;
  519.   Newsize: Integer;
  520. Begin
  521.   If I >= Size Then
  522.   Begin
  523.     Newsize := (I + Delta) Div Delta * Delta;
  524.     Getmem(P, Newsize * Sizeof(Longint));
  525.     If P <> Nil Then
  526.     Begin
  527.       Move(Index^, P^, Size * Sizeof(Longint));
  528.       Fillchar(P^[Size], (Newsize - Size) * Sizeof(Longint), $Ff);
  529.     End;
  530.     If Size > 0 Then Freemem(Index, Size * Sizeof(Longint));
  531.     Index := P;
  532.     Size := Newsize;
  533.   End;
  534.   Index^[I] := Val;
  535. End;
  536.  
  537. Procedure Thelpindex.Store(Var S: Tstream);
  538. Begin
  539.   S.Write(Size, Sizeof(Size));
  540.   S.Write(Index^, Sizeof(Longint) * Size);
  541. End;
  542.  
  543. { THelpFile }
  544.  
  545. Const
  546.   Magicheader = $46484246; {'Fbhf'}
  547.  
  548. Constructor Thelpfile.Init(S: Pstream);
  549. Var
  550.   Magic: Longint;
  551. Begin
  552.   Magic := 0;
  553.   S^.Seek(0);
  554.   If S^.Getsize > Sizeof(Magic) Then
  555.     S^.Read(Magic, Sizeof(Magic));
  556.   If Magic <> Magicheader Then
  557.   Begin
  558.     Indexpos := 12;
  559.     S^.Seek(Indexpos);
  560.     Index := New(Phelpindex, Init);
  561.     Modified := True;
  562.   End
  563.   Else
  564.   Begin
  565.     S^.Seek(8);
  566.     S^.Read(Indexpos, Sizeof(Indexpos));
  567.     S^.Seek(Indexpos);
  568.     Index := Phelpindex(S^.Get);
  569.     Modified := False;
  570.   End;
  571.   Stream := S;
  572. End;
  573.  
  574. Destructor Thelpfile.Done;
  575. Var
  576.   Magic, Size: Longint;
  577. Begin
  578.   If Modified Then
  579.   Begin
  580.     Stream^.Seek(Indexpos);
  581.     Stream^.Put(Index);
  582.     Stream^.Seek(0);
  583.     Magic := Magicheader;
  584.     Size := Stream^.Getsize - 8;
  585.     Stream^.Write(Magic, Sizeof(Magic));
  586.     Stream^.Write(Size, Sizeof(Size));
  587.     Stream^.Write(Indexpos, Sizeof(Indexpos));
  588.   End;
  589.   Dispose(Stream, Done);
  590.   Dispose(Index, Done);
  591. End;
  592.  
  593. Function Thelpfile.Gettopic(I: Integer): Phelptopic;
  594. Var
  595.   Pos: Longint;
  596. Begin
  597.   Pos := Index^.Position(I);
  598.   If Pos > 0 Then
  599.   Begin
  600.     Stream^.Seek(Pos);
  601.     Gettopic := Phelptopic(Stream^.Get);
  602.   End
  603.   Else Gettopic := Invalidtopic;
  604. End;
  605.  
  606. Function Thelpfile.Invalidtopic: Phelptopic;
  607. Var
  608.   Topic: Phelptopic;
  609.   Para: Pparagraph;
  610. Const
  611.   Invalidstr = #13' Ayuda no disponible en este contexto.';
  612.   Invalidtext: Array[1..Length(Invalidstr)] Of Char = Invalidstr;
  613. Begin
  614.   Topic := New(Phelptopic, Init);
  615.   Getmem(Para, Sizeof(Para^) + Sizeof(Invalidtext));
  616.   Para^.Size := Sizeof(Invalidtext);
  617.   Para^.Wrap := False;
  618.   Para^.Next := Nil;
  619.   Move(Invalidtext, Para^.Text, Sizeof(Invalidtext));
  620.   Topic^.Addparagraph(Para);
  621.   Invalidtopic := Topic;
  622. End;
  623.  
  624. Procedure Thelpfile.Recordpositioninindex(I: Integer);
  625. Begin
  626.   Index^.Add(I, Indexpos);
  627.   Modified := True;
  628. End;
  629.  
  630. Procedure Thelpfile.Puttopic(Topic: Phelptopic);
  631. Begin
  632.   Stream^.Seek(Indexpos);
  633.   Stream^.Put(Topic);
  634.   Indexpos := Stream^.Getpos;
  635.   Modified := True;
  636. End;
  637.  
  638. { THelpViewer }
  639.  
  640. Constructor Thelpviewer.Init(Var Bounds: Trect; Ahscrollbar,
  641.   Avscrollbar: Pscrollbar; Ahelpfile: Phelpfile; Context: Word);
  642. Begin
  643.   Tscroller.Init(Bounds, Ahscrollbar, Avscrollbar);
  644.   Options := Options Or Ofselectable;
  645.   Growmode := Gfgrowhix + Gfgrowhiy;
  646.   Hfile := Ahelpfile;
  647.   Topic := Ahelpfile^.Gettopic(Context);
  648.   Topic^.Setwidth(Size.X);
  649.   Setlimit(78, Topic^.Numlines);
  650.   Selected := 1;
  651. End;
  652.  
  653. Destructor Thelpviewer.Done;
  654. Begin
  655.   Tscroller.Done;
  656.   Dispose(Hfile, Done);
  657.   Dispose(Topic, Done);
  658. End;
  659.  
  660. Procedure Thelpviewer.Changebounds(Var Bounds: Trect);
  661. Begin
  662.   Tscroller.Changebounds(Bounds);
  663.   Topic^.Setwidth(Size.X);
  664.   Setlimit(Limit.X, Topic^.Numlines);
  665. End;
  666.  
  667. Procedure Thelpviewer.Draw;
  668. Var
  669.   B: Tdrawbuffer;
  670.   Line: String;
  671.   I, J, L: Integer;
  672.   Keycount: Integer;
  673.   Normal, Keyword, Selkeyword, C: Byte;
  674.   Keypoint: Tpoint;
  675.   Keylength: Byte;
  676.   Keyref: Integer;
  677. Begin
  678.   Normal := Getcolor(1);
  679.   Keyword := Getcolor(2);
  680.   Selkeyword := Getcolor(3);
  681.   Keycount := 0;
  682.   Keypoint.X := 0;
  683.   Keypoint.Y := 0;
  684.   Topic^.Setwidth(Size.X);
  685.   If Topic^.Getnumcrossrefs > 0 Then
  686.     Repeat
  687.       Inc(Keycount);
  688.       Topic^.Getcrossref(Keycount, Keypoint, Keylength, Keyref);
  689.     Until (Keycount >= Topic^.Getnumcrossrefs) Or (Keypoint.Y > Delta.Y);
  690.   For I := 1 To Size.Y Do
  691.   Begin
  692.     Movechar(B, ' ', Normal, Size.X);
  693.     Line := Topic^.Getline(I + Delta.Y);
  694.     Movestr(B, Copy(Line, Delta.X+1, Size.X), Normal);
  695.     While I + Delta.Y = Keypoint.Y Do
  696.     Begin
  697.       L := Keylength;
  698.       If Keypoint.X < Delta.X Then
  699.       Begin
  700.         Dec(L, Delta.X - Keypoint.X);
  701.         Keypoint.X := Delta.X;
  702.       End;
  703.       If Keycount = Selected Then C := Selkeyword
  704.       Else C := Keyword;
  705.       For J := 0 To L-1 Do
  706.         Wordrec(B[Keypoint.X - Delta.X + J]).Hi := C;
  707.       Inc(Keycount);
  708.       If Keycount <= Topic^.Getnumcrossrefs Then
  709.         Topic^.Getcrossref(Keycount, Keypoint, Keylength, Keyref)
  710.       Else Keypoint.Y := 0;
  711.     End;
  712.     Writeline(0, I-1, Size.X, 1, B);
  713.   End;
  714. End;
  715.  
  716. Function Thelpviewer.Getpalette: Ppalette;
  717. Const
  718.   P: String[Length(Chelpviewer)] = Chelpviewer;
  719. Begin
  720.   Getpalette := @P;
  721. End;
  722.  
  723. Procedure Thelpviewer.Handleevent(Var Event: Tevent);
  724. Var
  725.   Keypoint, Mouse: Tpoint;
  726.   Keylength: Byte;
  727.   Keyref: Integer;
  728.   Keycount: Integer;
  729.  
  730. Procedure Makeselectvisible;
  731. Var
  732.   D: Tpoint;
  733. Begin
  734.   Topic^.Getcrossref(Selected, Keypoint, Keylength, Keyref);
  735.   D := Delta;
  736.   If Keypoint.X < D.X Then D.X := Keypoint.X;
  737.   If Keypoint.X > D.X + Size.X Then D.X := Keypoint.X - Size.X;
  738.   If Keypoint.Y < D.Y Then D.Y := Keypoint.Y;
  739.   If Keypoint.Y > D.Y + Size.Y Then D.Y := Keypoint.Y - Size.Y;
  740.   If (D.X <> Delta.X) Or (D.Y <> Delta.Y) Then Scrollto(D.X, D.Y);
  741. End;
  742.  
  743. Procedure Switchtotopic(Keyref: Integer);
  744. Begin
  745.   If Topic <> Nil Then Dispose(Topic, Done);
  746.   Topic := Hfile^.Gettopic(Keyref);
  747.   Topic^.Setwidth(Size.X);
  748.   Scrollto(0, 0);
  749.   Setlimit(Limit.X, Topic^.Numlines);
  750.   Selected := 1;
  751.   Drawview;
  752. End;
  753.  
  754. Begin
  755.   Tscroller.Handleevent(Event);
  756.   Case Event.What Of
  757.     Evkeydown:
  758.       Begin
  759.         Case Event.Keycode Of
  760.           Kbtab:
  761.             Begin
  762.               Inc(Selected);
  763.               If Selected > Topic^.Getnumcrossrefs Then Selected := 1;
  764.               Makeselectvisible;
  765.             End;
  766.           Kbshifttab:
  767.             Begin
  768.               Dec(Selected);
  769.               If Selected = 0 Then Selected := Topic^.Getnumcrossrefs;
  770.               Makeselectvisible;
  771.             End;
  772.           Kbenter:
  773.             Begin
  774.               If Selected <= Topic^.Getnumcrossrefs Then
  775.               Begin
  776.                 Topic^.Getcrossref(Selected, Keypoint, Keylength, Keyref);
  777.                 Switchtotopic(Keyref);
  778.               End;
  779.             End;
  780.           Kbesc:
  781.             Begin
  782.               Event.What := Evcommand;
  783.               Event.Command := Cmclose;
  784.               Putevent(Event);
  785.             End;
  786.         Else
  787.           Exit;
  788.         End;
  789.         Drawview;
  790.         Clearevent(Event);
  791.       End;
  792.     Evmousedown:
  793.       Begin
  794.         Makelocal(Event.Where, Mouse);
  795.         Inc(Mouse.X, Delta.X); Inc(Mouse.Y, Delta.Y);
  796.         Keycount := 0;
  797.         Repeat
  798.           Inc(Keycount);
  799.           If Keycount > Topic^.Getnumcrossrefs Then Exit;
  800.           Topic^.Getcrossref(Keycount, Keypoint, Keylength, Keyref);
  801.         Until (Keypoint.Y = Mouse.Y+1) And (Mouse.X >= Keypoint.X) And
  802.           (Mouse.X < Keypoint.X + Keylength);
  803.         Selected := Keycount;
  804.         Drawview;
  805.         If Event.Double Then Switchtotopic(Keyref);
  806.         Clearevent(Event);
  807.       End;
  808.     Evcommand:
  809.       If (Event.Command = Cmclose) And (Owner^.State And Sfmodal <> 0) Then
  810.       Begin
  811.         Endmodal(Cmclose);
  812.         Clearevent(Event);
  813.       End;
  814.   End;
  815. End;
  816.  
  817. { THelpWindow }
  818.  
  819. Constructor Thelpwindow.Init(Hfile: Phelpfile; Context: Word);
  820. Var
  821.   R: Trect;
  822. Begin
  823.   R.Assign(0, 0, 50, 18);
  824.   Twindow.Init(R, 'Ayuda', Wnnonumber);
  825.   Options := Options Or Ofcentered;
  826.   R.Grow(-2,-1);
  827.   Insert(New(Phelpviewer, Init(R,
  828.     Standardscrollbar(Sbhorizontal + Sbhandlekeyboard),
  829.     Standardscrollbar(Sbvertical + Sbhandlekeyboard), Hfile, Context)));
  830. End;
  831.  
  832. Function Thelpwindow.Getpalette: Ppalette;
  833. Const
  834.   P: String[Length(Chelpwindow)] = Chelpwindow;
  835. Begin
  836.   Getpalette := @P;
  837. End;
  838.  
  839. Procedure Registerhelpfile;
  840. Begin
  841.   Registertype(Rhelptopic);
  842.   Registertype(Rhelpindex);
  843. End;
  844.  
  845. Procedure Notassigned(Var S: Tstream; Value: Integer);
  846. Begin
  847. End;
  848.  
  849. End.
  850.